using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace App1
{
    /// <summary>
    /// 文件共享帮助类
    /// </summary>
    public class FileShareHelper
    {
        private const int Port = 8888;
        private const string BroadcastAddress = "255.255.255.255";
        private UdpClient _udpClient;
        private TcpListener _tcpListener;
        private bool _isSharing = false;
        private string _sharedFolderPath;

        /// <summary>
        /// 文件共享事件
        /// </summary>
        public event EventHandler<FileShareEventArgs> FileShared;

        /// <summary>
        /// 开始共享文件
        /// </summary>
        /// <param name="folderPath">共享文件夹路径</param>
        public async Task StartSharingAsync(string folderPath)
        {
            if (_isSharing)
                return;

            _sharedFolderPath = folderPath;
            _isSharing = true;

            // 启动UDP广播服务
            StartUdpBroadcast();

            // 启动TCP监听服务
            StartTcpListener();

            // 扫描共享文件夹
            await ScanSharedFolderAsync();
        }

        /// <summary>
        /// 停止共享文件
        /// </summary>
        public void StopSharing()
        {
            if (!_isSharing)
                return;

            _isSharing = false;

            // 关闭UDP客户端
            _udpClient?.Close();
            _udpClient = null;

            // 关闭TCP监听器
            _tcpListener?.Stop();
            _tcpListener = null;
        }

        /// <summary>
        /// 启动UDP广播服务
        /// </summary>
        private void StartUdpBroadcast()
        {
            _udpClient = new UdpClient(Port);
            _udpClient.EnableBroadcast = true;

            // 发送广播消息
            Task.Run(async () =>
            {
                while (_isSharing)
                {
                    try
                    {
                        var message = Encoding.UTF8.GetBytes("FileShareServer");
                        await _udpClient.SendAsync(message, message.Length, new IPEndPoint(IPAddress.Parse(BroadcastAddress), Port));
                        await Task.Delay(5000); // 每5秒发送一次广播
                    }
                    catch (Exception ex)
                    {
                        // 处理异常
                    }
                }
            });

            // 接收UDP消息
            Task.Run(async () =>
            {
                while (_isSharing)
                {
                    try
                    {
                        var result = await _udpClient.ReceiveAsync();
                        var message = Encoding.UTF8.GetString(result.Buffer);

                        if (message == "FileShareClient")
                        {
                            // 响应客户端请求
                            var response = Encoding.UTF8.GetBytes("FileShareServerResponse");
                            await _udpClient.SendAsync(response, response.Length, result.RemoteEndPoint);
                        }
                    }
                    catch (Exception ex)
                    {
                        // 处理异常
                    }
                }
            });
        }

        /// <summary>
        /// 启动TCP监听服务
        /// </summary>
        private void StartTcpListener()
        {
            _tcpListener = new TcpListener(IPAddress.Any, Port + 1);
            _tcpListener.Start();

            Task.Run(async () =>
            {
                while (_isSharing)
                {
                    try
                    {
                        var client = await _tcpListener.AcceptTcpClientAsync();
                        // 处理客户端连接
                        HandleClientConnection(client);
                    }
                    catch (Exception ex)
                    {
                        // 处理异常
                    }
                }
            });
        }

        /// <summary>
        /// 处理客户端连接
        /// </summary>
        private async void HandleClientConnection(TcpClient client)
        {
            try
            {
                using (client)
                using (var stream = client.GetStream())
                {
                    // 读取请求
                    var buffer = new byte[1024];
                    var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                    var request = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    // 解析请求
                    if (request.StartsWith("LIST"))
                    {
                        // 列出文件
                        var files = await GetFileListAsync();
                        var response = JsonSerializer.Serialize(files);
                        var responseBytes = Encoding.UTF8.GetBytes(response);
                        await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
                    }
                    else if (request.StartsWith("DOWNLOAD"))
                    {
                        // 下载文件
                        var filePath = request.Substring("DOWNLOAD ".Length);
                        await SendFileAsync(stream, filePath);
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
            }
        }

        /// <summary>
        /// 扫描共享文件夹
        /// </summary>
        private async Task ScanSharedFolderAsync()
        {
            if (!Directory.Exists(_sharedFolderPath))
                return;

            var files = await Task.Run(() =>
            {
                return Directory.GetFiles(_sharedFolderPath, "*.*", SearchOption.AllDirectories)
                    .Select(path => new FileShareItem
                    {
                        Name = Path.GetFileName(path),
                        Path = path,
                        Size = new FileInfo(path).Length,
                        Type = GetFileShareType(path)
                    })
                    .ToList();
            });

            // 触发文件共享事件
            FileShared?.Invoke(this, new FileShareEventArgs { Files = files });
        }

        /// <summary>
        /// 获取文件列表
        /// </summary>
        private async Task<List<FileShareItem>> GetFileListAsync()
        {
            if (!Directory.Exists(_sharedFolderPath))
                return new List<FileShareItem>();

            return await Task.Run(() =>
            {
                return Directory.GetFiles(_sharedFolderPath, "*.*", SearchOption.AllDirectories)
                    .Select(path => new FileShareItem
                    {
                        Name = Path.GetFileName(path),
                        Path = path,
                        Size = new FileInfo(path).Length,
                        Type = GetFileShareType(path)
                    })
                    .ToList();
            });
        }

        /// <summary>
        /// 发送文件
        /// </summary>
        private async Task SendFileAsync(NetworkStream stream, string filePath)
        {
            if (!File.Exists(filePath))
            {
                var error = Encoding.UTF8.GetBytes("ERROR: File not found");
                await stream.WriteAsync(error, 0, error.Length);
                return;
            }

            // 发送文件信息
            var fileInfo = new FileInfo(filePath);
            var fileInfoJson = JsonSerializer.Serialize(new
            {
                Name = fileInfo.Name,
                Size = fileInfo.Length
            });
            var fileInfoBytes = Encoding.UTF8.GetBytes(fileInfoJson);
            await stream.WriteAsync(fileInfoBytes, 0, fileInfoBytes.Length);

            // 等待确认
            var buffer = new byte[1024];
            var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            var confirm = Encoding.UTF8.GetString(buffer, 0, bytesRead);

            if (confirm != "READY")
                return;

            // 发送文件内容
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                var fileBuffer = new byte[8192];
                int bytesReadFromFile;
                while ((bytesReadFromFile = await fileStream.ReadAsync(fileBuffer, 0, fileBuffer.Length)) > 0)
                {
                    await stream.WriteAsync(fileBuffer, 0, bytesReadFromFile);
                }
            }
        }

        /// <summary>
        /// 获取文件类型
        /// </summary>
        private FileShareType GetFileShareType(string filePath)
        {
            var extension = Path.GetExtension(filePath).ToLower();

            if (extension == ".mp4" || extension == ".avi" || extension == ".mkv" || extension == ".mov")
                return FileShareType.Video;
            else if (extension == ".mp3" || extension == ".wav" || extension == ".flac" || extension == ".aac")
                return FileShareType.Audio;
            else if (extension == ".jpg" || extension == ".jpeg" || extension == ".png" || extension == ".gif")
                return FileShareType.Image;
            else
                return FileShareType.Other;
        }

        /// <summary>
        /// 发现局域网中的文件共享服务
        /// </summary>
        public async Task<List<IPEndPoint>> DiscoverFileShareServicesAsync()
        {
            var services = new List<IPEndPoint>();
            var client = new UdpClient();
            client.EnableBroadcast = true;

            try
            {
                // 发送广播请求
                var request = Encoding.UTF8.GetBytes("FileShareClient");
                await client.SendAsync(request, request.Length, new IPEndPoint(IPAddress.Parse(BroadcastAddress), Port));

                // 设置接收超时
                client.Client.ReceiveTimeout = 3000;

                // 接收响应
                while (true)
                {
                    try
                    {
                        var result = await client.ReceiveAsync();
                        var response = Encoding.UTF8.GetString(result.Buffer);

                        if (response == "FileShareServerResponse")
                        {
                            services.Add(result.RemoteEndPoint);
                        }
                    }
                    catch (SocketException ex)
                    {
                        // 超时异常，结束接收
                        if (ex.SocketErrorCode == SocketError.TimedOut)
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
            }
            finally
            {
                client.Close();
            }

            return services;
        }

        /// <summary>
        /// 从远程服务获取文件列表
        /// </summary>
        public async Task<List<FileShareItem>> GetRemoteFileListAsync(IPEndPoint endPoint)
        {
            try
            {
                using (var client = new TcpClient())
                {
                    await client.ConnectAsync(endPoint.Address, Port + 1);
                    using (var stream = client.GetStream())
                    {
                        // 发送请求
                        var request = Encoding.UTF8.GetBytes("LIST");
                        await stream.WriteAsync(request, 0, request.Length);

                        // 接收响应
                        var buffer = new byte[4096];
                        var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                        var response = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                        // 解析文件列表
                        return JsonSerializer.Deserialize<List<FileShareItem>>(response);
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
                return new List<FileShareItem>();
            }
        }

        /// <summary>
        /// 从远程服务下载文件
        /// </summary>
        public async Task DownloadFileAsync(IPEndPoint endPoint, string remoteFilePath, string savePath, IProgress<double> progress = null)
        {
            try
            {
                using (var client = new TcpClient())
                {
                    await client.ConnectAsync(endPoint.Address, Port + 1);
                    using (var stream = client.GetStream())
                    {
                        // 发送下载请求
                        var request = Encoding.UTF8.GetBytes($"DOWNLOAD {remoteFilePath}");
                        await stream.WriteAsync(request, 0, request.Length);

                        // 接收文件信息
                        var buffer = new byte[1024];
                        var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                        var fileInfoJson = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                        if (fileInfoJson.StartsWith("ERROR"))
                        {
                            throw new Exception(fileInfoJson);
                        }

                        // 解析文件信息
                        var fileInfo = JsonSerializer.Deserialize<dynamic>(fileInfoJson);
                        long fileSize = fileInfo.Size;

                        // 确认接收
                        var confirm = Encoding.UTF8.GetBytes("READY");
                        await stream.WriteAsync(confirm, 0, confirm.Length);

                        // 创建保存文件的目录
                        Directory.CreateDirectory(Path.GetDirectoryName(savePath));

                        // 接收文件内容
                        using (var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                        {
                            long totalBytesRead = 0;
                            var fileBuffer = new byte[8192];
                            int bytesReadFromStream;

                            while ((bytesReadFromStream = await stream.ReadAsync(fileBuffer, 0, fileBuffer.Length)) > 0)
                            {
                                await fileStream.WriteAsync(fileBuffer, 0, bytesReadFromStream);
                                totalBytesRead += bytesReadFromStream;

                                // 报告进度
                                if (progress != null && fileSize > 0)
                                {
                                    double progressPercentage = (double)totalBytesRead / fileSize * 100;
                                    progress.Report(progressPercentage);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
                throw;
            }
        }
    }

    /// <summary>
    /// 文件共享事件参数
    /// </summary>
    public class FileShareEventArgs : EventArgs
    {
        public List<FileShareItem> Files { get; set; }
    }

    /// <summary>
    /// 文件类型
    /// </summary>
    public enum FileShareType
    {
        Video,
        Audio,
        Image,
        Other
    }

    /// <summary>
    /// 文件项
    /// </summary>
    public class FileShareItem
    {
        public string Name { get; set; }
        public string Path { get; set; }
        public long Size { get; set; }
        public FileShareType Type { get; set; }

        /// <summary>
        /// 获取文件图标字符
        /// </summary>
        public string Glyph
        {
            get
            {
                switch (Type)
                {
                    case FileShareType.Video:
                        return "\uE714";
                    case FileShareType.Audio:
                        return "\uE7FC";
                    case FileShareType.Image:
                        return "\uE722";
                    default:
                        return "\uE8A5";
                }
            }
        }

        /// <summary>
        /// 获取格式化的文件大小
        /// </summary>
        public string FormattedSize
        {
            get
            {
                if (Size < 1024)
                    return $"{Size} B";
                else if (Size < 1024 * 1024)
                    return $"{(Size / 1024.0):F2} KB";
                else if (Size < 1024 * 1024 * 1024)
                    return $"{(Size / (1024.0 * 1024.0)):F2} MB";
                else
                    return $"{(Size / (1024.0 * 1024.0 * 1024.0)):F2} GB";
            }
        }
    }
}